package com.linciping.useges.plugin.asyc;

import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiManager;
import com.linciping.useges.plugin.bean.File2R;
import com.linciping.useges.plugin.bean.PsiFile2Content;
import com.linciping.useges.plugin.bean.Res2SourceFile;
import com.linciping.useges.plugin.listener.ThreadFinishListener;
import com.linciping.useges.plugin.util.Util;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.psi.KtFile;

import java.util.List;
import java.util.concurrent.ExecutionException;

public abstract class ResUsegesThread implements Runnable {

    protected final Project project;
    protected final Module targetModule;
    private final List<File2R> resRList;
    @Nullable
    private ThreadFinishListener threadFinishListener;

    public void setThreadFinishListener(@Nullable ThreadFinishListener threadFinishListener) {
        this.threadFinishListener = threadFinishListener;
    }

    public ResUsegesThread(Project project, Module targetModule, List<File2R> resRList) {
        this.project = project;
        this.targetModule = targetModule;
        this.resRList = resRList;
    }

    protected void callFinish() {
        if (threadFinishListener != null) {
            threadFinishListener.onFinish();
        }
    }

    protected abstract List<Res2SourceFile> executorFind(List<List<File2R>> file2RPool, List<PsiFile2Content> waitFindPsiFileContentList) throws ExecutionException, InterruptedException;

    protected void buildSource(Project project, VirtualFile sourceFile, List<Res2SourceFile> res2SourceFileList, List<PsiFile2Content> waitFindPsiFileContentList) {
        PsiDirectory psiDirectory = PsiManager.getInstance(project).findDirectory(sourceFile);
        assert psiDirectory != null;
        buildPackage(waitFindPsiFileContentList, psiDirectory);
        List<List<File2R>> file2RPool = Util.splitResFile(resRList);
        try {
            res2SourceFileList.addAll(executorFind(file2RPool, waitFindPsiFileContentList));
        } catch (ExecutionException | InterruptedException e) {
            System.err.println(e.getMessage());
        }
    }

    protected void buildPackage(List<PsiFile2Content> waitFindPsiFileContentList, PsiDirectory psiDirectory) {
        PsiFile[] psiFiles = psiDirectory.getFiles();
        if (psiFiles.length > 0) {
            for (PsiFile psiFile : psiFiles) {
                if (psiFile.isValid() && ((psiFile instanceof PsiJavaFile) || (psiFile instanceof KtFile))) {
                    waitFindPsiFileContentList.add(new PsiFile2Content(psiFile, psiFile.getText()));
                }
            }
        }
        PsiDirectory[] psiDirectories = psiDirectory.getSubdirectories();
        if (psiDirectories.length > 0) {
            for (PsiDirectory child : psiDirectories) {
                buildPackage(waitFindPsiFileContentList, child);
            }
        }
    }
}
